﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data;
using System.Reflection;
using log4net;

namespace ProjectBuilder
{
    abstract public class BaseObject
    {
        /// <summary>
        /// Проект до якого відноситься каталог
        /// </summary>
        //public Project Project { get; set; }

        [DbField("build_id", IsUniqField = false)]
        public long? BuildId { get; set; }

        /// <summary>
        /// Флаг чи новий елемент в базі
        /// </summary>
        [DbField("new", IsUniqField = false)]
        public bool IsNew { get; set; }

        /// <summary>
        /// Бере значення поля об'єкта
        /// </summary>
        /// <param name="oObj">об'єкт</param>
        /// <param name="sName">назва поля</param>
        /// <returns>значення поля</returns>
        protected static object GetField(object oObj, string sName)
        {
            return (oObj.GetType().InvokeMember(sName,
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty,
                null, oObj, new object[] { }));
        }

        /// <summary>
        /// Повертає список полів, які потрібні для генерації запиту вставки в БД
        /// </summary>
        /// <param name="oObj">об'єкт</param>
        /// <returns>список ключ-значення</returns>
        protected static Dictionary<string, object> getFields(BaseObject oObj)
        {
            return getFields(oObj, false);
        }

        /// <summary>
        /// Повертає список полів, які потрібні для генерації
        /// </summary>
        /// <param name="oObj">об'єкт</param>
        /// <param name="uniq">флаг унікального поля, якщо так, то для вибірка, якщо ні - вставка</param>
        /// <returns>список ключ-значення</returns>
        protected static Dictionary<string, object> getFields(BaseObject oObj, bool uniq)
        {
            Type type = oObj.GetType();
            var dict = new Dictionary<string, object>();

            var Members = type.GetMembers(BindingFlags.Instance |
                                          BindingFlags.Public |
                                          BindingFlags.GetProperty |
                                          BindingFlags.SetField);
            foreach (var Member in Members)
            {
                var attrs = Member.GetCustomAttributes(typeof(DbFieldAttribute), true);
                if (attrs.Length == 0) continue;
                var attr = attrs[0] as DbFieldAttribute;
                var oField = GetField(oObj, Member.Name);
                if ((attr.IsNullable || oField != null) &&
                    (!uniq || attr.IsUniqField))
                {
                    dict.Add(attr.FieldName, oField);
                }
            }
            return (dict);
        }

        /// <summary>
        /// Генерує список полів і їх значень для запису вставки/оновлення
        /// </summary>
        /// <param name="fields">поля</param>
        /// <param name="cmd">команда куди додавати поля</param>
        /// <returns>список полів(ключ-значення)</returns>
        protected Dictionary<string, string> getQueryField(Dictionary<string, object> fields, ref MySqlCommand cmd)
        {
            var values = new Dictionary<string, string>();
            foreach (var field in fields)
            {
                var val = "@" + field.Key;
                switch (field.Key)
                {
                    case "new":
                        val = "1";
                        break;
                    /*case "update_time":
                        val = "FROM_UNIXTIME(" + Globals.Project.UpdateTime.ToUnixTime() + ")";
                        break;*/
                    case "build_id":
                        val = Globals.Project.BuildId.ToString();
                        break;
                    default:
                        cmd.Parameters.AddWithValue(field.Key, field.Value);
                        break;
                }
                values.Add(field.Key, val);
            }
            return values;
        }
    }
}
